/**
 * Frida脚本：捕获ep加密前的原始值（即AES密钥）
 * 
 * 目标：在SO代码中找到ep被RSA加密之前的位置，捕获原始值
 */

console.log("\n" + "=".repeat(80));
console.log("数美SDK - 捕获ep原始值（AES密钥）");
console.log("=".repeat(80));

// 工具函数
function bytesToHex(bytes) {
    if (!bytes) return "null";
    let hex = "";
    for (let i = 0; i < bytes.length; i++) {
        hex += ("0" + bytes[i].toString(16)).slice(-2);
    }
    return hex;
}

function hexToBytes(hex) {
    const bytes = [];
    for (let i = 0; i < hex.length; i += 2) {
        bytes.push(parseInt(hex.substr(i, 2), 16));
    }
    return bytes;
}

function printBuffer(label, buf, maxLen = 128) {
    if (!buf) {
        console.log(label + ": null");
        return;
    }
    const len = buf.length;
    const displayLen = Math.min(len, maxLen);
    const bytes = [];
    for (let i = 0; i < displayLen; i++) {
        bytes.push(buf[i]);
    }
    console.log(label + ": (" + len + " bytes)");
    console.log("  Hex: " + bytesToHex(bytes));
    if (len > maxLen) {
        console.log("  (truncated, showing first " + maxLen + " of " + len + " bytes)");
    }
}

// 加载SO库
const soName = "libsmsdk.so";
let soModule = null;

function waitForModule() {
    soModule = Process.findModuleByName(soName);
    if (soModule) {
        console.log("✓ 找到SO库: " + soName);
        console.log("  Base: " + soModule.base);
        console.log("  Size: " + soModule.size);
        hookEPGeneration();
    } else {
        console.log("⏳ 等待SO库加载: " + soName);
        setTimeout(waitForModule, 100);
    }
}

function hookEPGeneration() {
    console.log("\n" + "-".repeat(80));
    console.log("策略1: Hook可能的密钥生成函数");
    console.log("-".repeat(80));
    
    // 根据SO代码分析，ep相关的处理可能在以下函数中
    // 我们需要找到生成随机密钥的位置
    
    // 常见的随机数生成函数
    const randomFuncs = [
        "RAND_bytes",
        "random",
        "rand",
        "arc4random",
        "getrandom"
    ];
    
    randomFuncs.forEach(funcName => {
        const funcPtr = Module.findExportByName(null, funcName);
        if (funcPtr) {
            console.log("✓ Hook " + funcName + " @ " + funcPtr);
            Interceptor.attach(funcPtr, {
                onEnter: function(args) {
                    this.buf = args[0];
                    this.len = args[1].toInt32();
                },
                onLeave: function(retval) {
                    if (this.len > 0 && this.len <= 256) {
                        const bytes = this.buf.readByteArray(this.len);
                        printBuffer("  " + funcName + " 生成", bytes);
                        
                        // 如果是32字节，很可能是AES-256密钥
                        if (this.len === 32) {
                            console.log("  ⚠️  这可能是AES-256密钥（32字节）！");
                        }
                    }
                }
            });
        }
    });
    
    console.log("\n" + "-".repeat(80));
    console.log("策略2: Hook RSA加密函数");
    console.log("-".repeat(80));
    
    // RSA加密函数
    const rsaFuncs = [
        "RSA_public_encrypt",
        "RSA_private_decrypt",
        "EVP_PKEY_encrypt",
        "EVP_PKEY_decrypt"
    ];
    
    rsaFuncs.forEach(funcName => {
        const funcPtr = Module.findExportByName(null, funcName);
        if (funcPtr) {
            console.log("✓ Hook " + funcName + " @ " + funcPtr);
            Interceptor.attach(funcPtr, {
                onEnter: function(args) {
                    // RSA_public_encrypt(int flen, unsigned char *from, unsigned char *to, RSA *rsa, int padding)
                    if (funcName === "RSA_public_encrypt") {
                        this.flen = args[0].toInt32();
                        this.from = args[1];
                        this.to = args[2];
                        
                        console.log("\n🔑 RSA_public_encrypt 调用:");
                        console.log("  输入长度: " + this.flen);
                        
                        if (this.flen > 0 && this.flen <= 256) {
                            const plaintext = this.from.readByteArray(this.flen);
                            printBuffer("  明文（可能是AES密钥）", plaintext);
                            
                            if (this.flen === 32) {
                                console.log("  ⚠️⚠️⚠️ 这很可能就是AES-256密钥！⚠️⚠️⚠️");
                            }
                        }
                    }
                },
                onLeave: function(retval) {
                    if (funcName === "RSA_public_encrypt" && this.flen > 0) {
                        const encLen = retval.toInt32();
                        if (encLen > 0) {
                            const ciphertext = this.to.readByteArray(encLen);
                            printBuffer("  密文（加密后的ep）", ciphertext);
                        }
                    }
                }
            });
        }
    });
    
    console.log("\n" + "-".repeat(80));
    console.log("策略3: Hook AES加密函数的密钥参数");
    console.log("-".repeat(80));
    
    // AES初始化函数
    const aesFuncs = [
        "AES_set_encrypt_key",
        "AES_set_decrypt_key",
        "EVP_EncryptInit_ex",
        "EVP_DecryptInit_ex"
    ];
    
    aesFuncs.forEach(funcName => {
        const funcPtr = Module.findExportByName(null, funcName);
        if (funcPtr) {
            console.log("✓ Hook " + funcName + " @ " + funcPtr);
            Interceptor.attach(funcPtr, {
                onEnter: function(args) {
                    // AES_set_encrypt_key(const unsigned char *userKey, const int bits, AES_KEY *key)
                    if (funcName.startsWith("AES_set")) {
                        const keyPtr = args[0];
                        const bits = args[1].toInt32();
                        const keyLen = bits / 8;
                        
                        console.log("\n🔐 " + funcName + " 调用:");
                        console.log("  密钥长度: " + bits + " bits (" + keyLen + " bytes)");
                        
                        if (keyLen > 0 && keyLen <= 64) {
                            const key = keyPtr.readByteArray(keyLen);
                            printBuffer("  AES密钥", key);
                        }
                    }
                }
            });
        }
    });
    
    console.log("\n" + "-".repeat(80));
    console.log("策略4: Hook SO内部函数（基于之前的分析）");
    console.log("-".repeat(80));
    
    // 根据之前的分析，sub_4AAE4是AES加密函数
    // sub_4AAE4(data, dataLen, output, key, keyLen, iv)
    const aesEncAddr = soModule.base.add(0x4AAE4);
    console.log("✓ Hook sub_4AAE4 (AES加密) @ " + aesEncAddr);
    
    Interceptor.attach(aesEncAddr, {
        onEnter: function(args) {
            const dataPtr = args[0];
            const dataLen = args[1].toInt32();
            const outputPtr = args[2];
            const keyPtr = args[3];
            const keyLen = args[4].toInt32();
            const ivPtr = args[5];
            
            console.log("\n🔐 sub_4AAE4 (AES加密) 调用:");
            console.log("  数据长度: " + dataLen);
            console.log("  密钥长度: " + keyLen);
            
            if (keyLen > 0 && keyLen <= 64) {
                const key = keyPtr.readByteArray(keyLen);
                printBuffer("  AES密钥", key);
                console.log("  ⚠️⚠️⚠️ 这就是我们要找的密钥！⚠️⚠️⚠️");
            }
            
            if (ivPtr && !ivPtr.isNull()) {
                const iv = ivPtr.readByteArray(16);
                printBuffer("  IV", iv);
            }
            
            if (dataLen > 0 && dataLen <= 4096) {
                const data = dataPtr.readByteArray(dataLen);
                printBuffer("  输入数据", data, 64);
            }
        },
        onLeave: function(retval) {
            console.log("  返回值: " + retval);
        }
    });
    
    console.log("\n✓ Hook设置完成，等待函数调用...\n");
}

// 启动
setTimeout(waitForModule, 100);



